package net.expectx.pay.controller;

import io.swagger.annotations.ApiOperation;
import net.expectx.pay.common.AdminConstants;
import net.expectx.pay.common.AdminResult;
import net.expectx.pay.dao.bean.*;
import net.expectx.pay.rpc.api.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author hxs
 */

@Controller
@RequestMapping(value = "/manager/dataStatistics")
public class DataStatisticsController {

    @Autowired
    private ProductOrderHeaderService productOrderHeaderService;
    @Autowired
    private PaymentChannelService paymentChannelService;
    @Autowired
    private SystemTypeService systemTypeService;
    @Autowired
    private MerchantUserService merchantUserService;

    private static final String PAY_SUCCESS_STATUS = "2";
    private static final String REFUND_SUCCESS_STATUS = "5";
    private static final Long ORDER_TYPE = 12L;
    private static final String ISREFUND_TYPE = "2";

    @ApiOperation(value = "数据统计主页")
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(ModelMap modelMap) {
        PaymentChannelExample paymentChannelExample = new PaymentChannelExample();
        PaymentChannelExample.Criteria criteria = paymentChannelExample.createCriteria();
        criteria.andIsDeletedEqualTo(AdminConstants.NO);
        List<PaymentChannel> paymentChannels = paymentChannelService.selectByExample(paymentChannelExample);
        modelMap.put("channels", paymentChannels);
        getTradeStatistics(modelMap, 0, 0, 0, null, null);
        return "dataStatistics/statistics";
    }

    @ApiOperation(value = "退款统计")
    @RequestMapping(value = "/refund", method = RequestMethod.GET)
    public String refund(ModelMap modelMap) {
        PaymentChannelExample paymentChannelExample = new PaymentChannelExample();
        PaymentChannelExample.Criteria criteria = paymentChannelExample.createCriteria();
        criteria.andIsDeletedEqualTo(AdminConstants.NO);
        List<PaymentChannel> paymentChannels = paymentChannelService.selectByExample(paymentChannelExample);
        modelMap.put("channels", paymentChannels);
        getTradeStatistics(modelMap, 0, 0, 0, null, ISREFUND_TYPE);
        return "dataStatistics/refund";
    }

    @ApiOperation(value = "数据统计")
    @RequestMapping(value = "/dataStatistics", method = RequestMethod.POST)
    @ResponseBody
    public Object dataStatistics(ModelMap modelMap, Long startTime, Long endTime, Long channel, String merchantNo) {
        Map<String, Object> result = getTradeStatistics(modelMap, startTime, endTime, channel, merchantNo, null);
        HashMap model = (HashMap) result.get("model");
        List tradeStatistics = (List) model.get("tradeStatistics");
        if (tradeStatistics.isEmpty()) {
            return new AdminResult(false, 200, null, null);
        }
        return new AdminResult(true, 200, null, result);
    }

    @ApiOperation(value = "退款统计")
    @RequestMapping(value = "/refund", method = RequestMethod.POST)
    @ResponseBody
    public Object refund(ModelMap modelMap, Long startTime, Long endTime, Long channel, String merchantNo) {
        Map<String, Object> result = getTradeStatistics(modelMap, startTime, endTime, channel, merchantNo, ISREFUND_TYPE);
        HashMap model = (HashMap) result.get("model");
        List tradeStatistics = (List) model.get("tradeStatistics");
        if (tradeStatistics.isEmpty()) {
            return new AdminResult(false, 200, null, null);
        }
        return new AdminResult(true, 200, null, result);
    }

    /**
     * 获取交易信息
     *
     * @return
     */
    public Map<String, Object> getTradeStatistics(ModelMap modelMap, long startTime, long endTime, long channelId, String merchantNo, String orderType) {
        Map<String, Object> result = new HashMap<>();
        List<TradeStatisticsVO> tradeStatisticsVOList = new ArrayList<>();
        /**
         * 交易笔数
         * 成功笔数
         * 成交金额
         * 服务费
         * 交易总金额
         */
        Long totalSum = 0L;
        Long succSum = 0L;
        BigDecimal bargainSum = new BigDecimal(0);
        BigDecimal serviceFeeSum = new BigDecimal(0);
        BigDecimal grandTotalSum = new BigDecimal(0);
        /**
         * 订单列表
         */
        ProductOrderHeaderExample productOrderHeaderExample = new ProductOrderHeaderExample();
        ProductOrderHeaderExample.Criteria criteria = productOrderHeaderExample.createCriteria();
        if (StringUtils.isNotBlank(merchantNo)) {
            criteria.andMerchantNoEqualTo(merchantNo);
        }
        criteria.andIsDeletedEqualTo(AdminConstants.NO);
        if (startTime != 0 && endTime != 0) {
            criteria.andOrderDateBetween(startTime, endTime);
        }
        if (StringUtils.isNotBlank(orderType)) {
            criteria.andOrderTypeEqualTo(orderType);
        }
        List<ProductOrderHeader> productOrderHeaders = productOrderHeaderService.selectByExample(productOrderHeaderExample);
        /***
         * 通道列表
         */
        PaymentChannelExample paymentChannelExample = new PaymentChannelExample();
        PaymentChannelExample.Criteria criteria1 = paymentChannelExample.createCriteria();
        criteria1.andIsDeletedEqualTo(AdminConstants.NO);
        if (channelId != 0) {
            criteria1.andIdEqualTo(channelId);
        }
        List<PaymentChannel> paymentChannels = paymentChannelService.selectByExample(paymentChannelExample);
        /**
         * 字典组
         */
        SystemTypeExample systemTypeExample = new SystemTypeExample();
        SystemTypeExample.Criteria TypeCriteria = systemTypeExample.createCriteria();
        TypeCriteria.andIsDeletedEqualTo(AdminConstants.NO);
        TypeCriteria.andTypeGroupIdEqualTo(ORDER_TYPE);
        List<SystemType> systemTypes = systemTypeService.selectByExample(systemTypeExample);
        /**
         * 商户列表
         */
        MerchantUserExample merchantUserExample = new MerchantUserExample();
        merchantUserExample.createCriteria().andIsDeletedEqualTo(AdminConstants.NO);
        List<MerchantUser> merchantUsers = merchantUserService.selectByExample(merchantUserExample);
        /**
         * 根据类型放入不同list
         * 以typeName为key list为value放入map
         */
        Map<String, List<ProductOrderHeader>> productOrderMap = new HashMap<>();
        for (SystemType systemType : systemTypes) {
            List<ProductOrderHeader> ProductOrderHeaderList = new ArrayList<>();
            for (ProductOrderHeader productOrderHeader : productOrderHeaders) {
                if (systemType.getTypeCode().equals(productOrderHeader.getOrderType())) {
                    ProductOrderHeaderList.add(productOrderHeader);
                }
            }
            if (!ProductOrderHeaderList.isEmpty()) {
                productOrderMap.put(systemType.getTypeName(), ProductOrderHeaderList);
            }
        }
        /**
         * 根据MerchantNo分组
         * 再遍历通道列表
         */
        for (MerchantUser merchantUser : merchantUsers) {
            for (PaymentChannel paymentChannel : paymentChannels) {
                TradeStatisticsVO tradeStatisticsVO = new TradeStatisticsVO("", paymentChannel.getName(), 0L, new BigDecimal(0), 0L, new BigDecimal(0), new BigDecimal(0), null);
                for (String key : productOrderMap.keySet()) {
                    for (ProductOrderHeader productOrderHeader : productOrderMap.get(key)) {
                        if (paymentChannel.getId().equals(Long.valueOf(productOrderHeader.getProductOrderPaymentRecord().getChannelPayway())) && merchantUser.getMerchantNo().equals(productOrderHeader.getMerchantNo())) {
                            tradeStatisticsVO.setMerchant(merchantUser.getCompany());
                            tradeStatisticsVO.setOrderType(key);
                            tradeStatisticsVO.setGrandTotal(tradeStatisticsVO.getGrandTotal().add(productOrderHeader.getGrandTotal()));
                            tradeStatisticsVO.setSum(tradeStatisticsVO.getSum() + 1);
                            totalSum++;
                            grandTotalSum = grandTotalSum.add(productOrderHeader.getGrandTotal());

                            boolean flag = false;
                            if (ISREFUND_TYPE.equals(productOrderHeader.getOrderType())) {
                                if (REFUND_SUCCESS_STATUS.equals(productOrderHeader.getOrderStatus())) {
                                    flag = true;
                                }
                            } else {
                                if (PAY_SUCCESS_STATUS.equals(productOrderHeader.getOrderStatus())) {
                                    flag = true;
                                }
                            }
                            if (flag) {
                                tradeStatisticsVO.setSuccessSum(tradeStatisticsVO.getSuccessSum() + 1);
                                tradeStatisticsVO.setSuccessTotal(tradeStatisticsVO.getSuccessTotal().add(productOrderHeader.getGrandTotal()));
                                tradeStatisticsVO.setServiceFee(tradeStatisticsVO.getServiceFee().add(productOrderHeader.getServiceFee()));
                                succSum++;
                                serviceFeeSum = serviceFeeSum.add(productOrderHeader.getServiceFee());
                                bargainSum = bargainSum.add(productOrderHeader.getGrandTotal());
                            }
                        }
                    }
                }
                if (tradeStatisticsVO.getSum() != 0) {
                    tradeStatisticsVOList.add(tradeStatisticsVO);
                }
            }
        }

        modelMap.put("tradeStatistics", tradeStatisticsVOList);
        modelMap.put("totalSum", totalSum);
        modelMap.put("succSum", succSum);
        modelMap.put("bargainSum", bargainSum);
        modelMap.put("serviceFeeSum", serviceFeeSum);
        modelMap.put("grandTotalSum", grandTotalSum);
        result.put("model", modelMap);
        return result;
    }
}
